<template>
  <div id="container" class="container"></div>
  <div class="weather">
    <a-card title="实时天气" v-if="state.weather">
      <p>城市/区：{{ state.weather?.province + "/" + state.weather?.city }}</p>
      <p>天气：{{ state.weather?.weather }}</p>
      <p>温度：{{ state.weather?.temperature }}℃</p>
      <p>风向：{{ state.weather?.windDirection }}</p>
      <p>风力：{{ state.weather?.windPower }}级</p>
      <p>空气湿度：{{ state.weather?.humidity }}</p>
      <p>发布时间：{{ state.weather?.reportTime }}</p>
    </a-card>
  </div>
  <div class="toolbar">
    <a-card title="点击获取经纬度">
      <div class="toolbar-item">
        <a-input :value="state.point[0]" addon-before="lng" />
        <a-input :value="state.point[1]" addon-before="lat" />
      </div>
      <a-input :value="state.address" addon-before="地址" />
    </a-card>
  </div>
</template>

<script setup lang="ts">
import AMapLoader from "@amap/amap-jsapi-loader";
import { message } from "ant-design-vue";
import { onMounted, reactive } from "vue";

const state = reactive<any>({
  center: [116.397778, 39.908472], // 地图中心点
  point: [116.397778, 39.908472], // 经纬度-lng lat
  map: null, // 地图实例
  marker: null, // 地图icon
  geocoder: null, // 逆解析实例
  address: "北京市东城区东华门街道天安门-城楼", // 地址
  weatherCity: "东城区",
  weather: null,
});

onMounted(() => {
  initMap();
});

/**
 * DOM初始化完成进行地图初始化
 */
const initMap = () => {
  AMapLoader.load({
    key: "你的key", // 申请好的Web端开发者Key，首次调用 load 时必填
    version: "2.0", // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
    // 需要使用的的插件列表
    plugins: [
      "AMap.Geocoder", // 逆向地理解码插件
      "AMap.Marker", // 点标记插件
    ],
  })
    .then((AMap) => {
      state.map = new AMap.Map("container", {
        viewMode: "3D", // 地图视图模式，默认为‘2D’，可选’3D’，选择‘3D’会显示 3D 地图效果。
        zoom: 12, // 地图显示的缩放级别
        center: state.center, // 初始化地图中心点位置
      });
      // 如果父组件传入了有效值 回显一个icon
      if (state.point.length > 0) {
        addMarker(AMap);
      }
      // 获取天气
      getWeather(AMap);
      // 监听用户的点击事件
      state.map.on("click", (e: any) => {
        state.point = [e.lnglat.lng, e.lnglat.lat];
        // 增加点标记
        addMarker(AMap);
        // 获取地址
        getAddress(AMap);
      });
    })
    .catch((e) => {
      message.error(e);
    });
};

/**
 * 增加点标记
 * @param AMap AMap
 */
const addMarker = (AMap: any) => {
  // 清除其他icon
  if (state.marker) {
    state.marker.setMap(null);
    state.marker = null;
  }
  // 重新渲染icon
  state.marker = new AMap.Marker({
    icon: "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
    size: new AMap.Size(53, 68), // 图标大小
    imageSize: new AMap.Size(53, 68),
    position: state.point, // icon经纬度
    offset: new AMap.Pixel(-28, -60), // icon中心点的偏移量
  });
  state.marker.setMap(state.map); // 设置icon
};

/**
 * 将经纬度转换为地址
 * @param AMap AMap
 */
const getAddress = (AMap: any) => {
  // 这里通过高德 SDK 完成。
  state.geocoder = new AMap.Geocoder({
    city: "全国", // 地理编码时，设置地址描述所在城市; 默认全国; 可选值：城市名（中文或中文全拼）、citycode、adcode
    radius: 3000, // 逆地理编码时，以给定坐标为中心点; 默认1000; 取值范围(0-3000)
    extensions: "all", // 逆地理编码时，返回信息的详略; 默认值：base，返回基本地址信息; 默认值：base，返回基本地址信息
  });
  // 调用逆解析方法 个人开发者调用量上限5000（次/日）
  state.geocoder.getAddress(state.point, function (status: any, result: any) {
    if (status === "complete" && result.regeocode) {
      state.address = result.regeocode.formattedAddress;
      AMap.plugin("AMap.Weather", function () {
        if (
          result.info === "OK" &&
          result.regeocode.addressComponent.district
        ) {
          state.weatherCity = result.regeocode.addressComponent.district;
          // 获取天气
          getWeather(AMap);
        } else {
          message.error("根据地址查询天气失败，请重新选择！");
        }
      });
    } else {
      message.error("根据地址查询位置失败，请重新选择！");
    }
  });
};

/**
 * 获取天气
 * @param AMap AMap
 */
const getWeather = (AMap: any) => {
  AMap.plugin("AMap.Weather", function () {
    const weather = new AMap.Weather();
    // 执行实时天气信息查询
    weather.getLive(state.weatherCity, function (err: any, data: any) {
      if (data) {
        state.weather = data;
      } else {
        message.error(err);
      }
    });
  });
};
</script>

<style lang="less" scoped>
.container {
  position: relative;
  width: 100%;
  height: 100%;
  border: 10px solid #ececec;
}
.toolbar {
  position: absolute;
  right: 10px;
  bottom: 10px;
  z-index: 99;
  max-width: 500px;
  .toolbar-item {
    display: flex;
    margin-bottom: 15px;
  }
}
.weather {
  position: absolute;
  right: 10px;
  bottom: 210px;
  z-index: 99;
}
</style>
